package Engine.PhysicEngine;

import org.lwjgl.util.vector.Vector2f;

import Engine.*;

public abstract class RigidBody extends PhysicObject {
	private double Luftwiederstand = 15;
	private double Gravitation = 10;
	int Weight = 100;
	private double xGeschwindigkeit = 0;
	private double yGeschwindigkeit = 0;
	private int xPosition = 0;
	private int yPosition = 0;
	private boolean isGrounded1 = false;
	public boolean FreezeRotation = true;
	public boolean FreezePosition = false;
	protected Vector2f rotation;
	Time _time;
	Engine engine;
	private Physic physic;

	private boolean Interacts = false;
	private BoxCollider collider;
	/*
	 * Der Origin vom Korper Befindet sich Links unten Momentan nur Rechteckie
	 * Collider vorhanden. muss bei bedarf von runden bearbeitet werden.
	 */
	public int Height;
	public int Width;

	public RigidBody() {
		rotation = new Vector2f();
	}

	public void init(Physic physic, int Height, int Width) {
		super.init(physic);
		// es wird ein super.init(engine, physic) benötigt; Die klasse dient
		// aber nut als abstracte klasse;
		this.setPhysic(physic);

		this.Height = Height;
		this.Width = Width;
		setyGeschwindigkeit(0);
		setxGeschwindigkeit(0);
		setCollider(new BoxCollider(Height - 1, Width - 1, 0, 0, this));
	}

	/*
	 * Gibt die Wirkung der Kraft in Poolarkoordinaten an. Wird von der Funktion
	 * dann in eine X und eine Y Geschwindigkeit umgerechnet. Die Winkel müssen
	 * als vielfaches von PI angegeben werden angegeben werden also: 360� = 2
	 * 90� = 0.5 ^ y | | / | / 90�| / 60� 0�
	 * ________________|/_____________________ \ X / x=cos(angle*PI)*power
	 * y=sin(angle*PI)*power
	 * 
	 * 
	 * ----\ Bei power = 10 und angle = 0.5 ----/ Eine Geschwidikeitszunahme von
	 * 10 pixel/s
	 */
	public void AddForce(float angle, float power) {

		setxGeschwindigkeit(getxGeschwindigkeit()
				+ Math.cos(angle * 3.141592654f) * power);

		setyGeschwindigkeit(getyGeschwindigkeit()
				+ Math.sin(angle * 3.141592654f) * power);

	}

	public void BeschleunigeX(float Power) {
		setxGeschwindigkeit(getxGeschwindigkeit() + Power * _time.getDelta());
	}

	public boolean isGrounded() {
		return isGrounded1;
	}

	public void updatePosition(Time time) {
	}

	public class UpdatePhy extends Thread{
		Time time;
		public UpdatePhy(Time time){
			this.time = time;
		}
		
		public void run(){
			getCollider().Xpos = getxPosition();
			getCollider().Ypos = getyPosition();
			_time = time;

			updatePhysic(time);
			if (!FreezePosition) {
				setInteracted(false);

				if (getxGeschwindigkeit() > 0)
					setxGeschwindigkeit(getxGeschwindigkeit()
							- (getLuftwiederstand() * time.getDelta()));
				if (getxGeschwindigkeit() < 0)
					setxGeschwindigkeit(getxGeschwindigkeit()
							+ (getLuftwiederstand() * time.getDelta()));

				setyGeschwindigkeit(getyGeschwindigkeit() + getGravitation()
						* time.getDelta());
				if (getyGeschwindigkeit() > 60)
					setyGeschwindigkeit(60);

				// Y/X-Collision
				int currentposy = getyPosition();
				int aimposy = (int) (currentposy + (getyGeschwindigkeit() * time
						.getDelta()));

				if (currentposy == aimposy)
					currentposy--;
				int currentpos = getxPosition();
				int aimpos = (int) (currentpos + (getxGeschwindigkeit() * time
						.getDelta()));

				if (currentpos == aimpos)
					currentpos--;
				for (int y = (int) currentposy; (int) y != (int) aimposy; y += 0) {
					if (aimposy > currentposy)
						y++;
					if (currentposy > aimposy)
						y--;
					getCollider().Ypos = y;

					for (int x = (int) currentpos; (int) x != (int) aimpos; x += 0) {
						if (aimpos > currentpos)
							x++;
						if (currentpos > aimpos)
							x--;
						// X-Collision

						getCollider().Xpos = x;
						float IX = getPhysic().InteractX(getCollider());

						if (IX != 0) {
							setxPosition(x);

						} else {
							x = aimpos;
							setxGeschwindigkeit(0);
							setInteracted(true);

						}

						float IY = getPhysic().InteractY(getCollider());

						if (IY != 0) {
							setyPosition(y);

						} else {
							y = aimposy;
							setyGeschwindigkeit(0);
							setInteracted(true);
						}
					}

				}

				updatePosition(time);
			}
			if (!FreezeRotation) {
				if (getxGeschwindigkeit() != 0)
					rotation.y = (float) Math.atan(getyGeschwindigkeit()
							/ getxGeschwindigkeit());
				else
					rotation.y = (float) (Math.PI / 2);
			}
		}
		
		
	}
	
	public void update(Time time) {

		UpdatePhy upy = new UpdatePhy(time);
		upy.start();

	}

	public abstract void updatePhysic(Time time);

	public int getxPosition() {
		return xPosition;
	}

	public void setxPosition(int xPosition) {
		this.xPosition = xPosition;
	}

	public int getyPosition() {
		return yPosition;
	}

	public void setyPosition(int yPosition) {
		this.yPosition = yPosition;

	}

	public double getxGeschwindigkeit() {
		return xGeschwindigkeit;
	}

	public void setxGeschwindigkeit(double xGeschwindigkeit) {
		this.xGeschwindigkeit = xGeschwindigkeit;
	}

	public double getyGeschwindigkeit() {
		return yGeschwindigkeit;
	}

	public void setyGeschwindigkeit(double yGeschwindigkeit) {
		this.yGeschwindigkeit = yGeschwindigkeit;
	}

	public Physic getPhysic() {
		return physic;
	}

	public void setPhysic(Physic physic) {
		this.physic = physic;
	}

	public BoxCollider getCollider() {
		return collider;
	}

	public void setCollider(BoxCollider collider) {
		this.collider = collider;
	}

	public double getGravitation() {
		return Gravitation;
	}

	public void setGravitation(double gravitation) {
		Gravitation = gravitation;
	}

	public double getLuftwiederstand() {
		return Luftwiederstand;
	}

	public void setLuftwiederstand(double luftwiederstand) {
		Luftwiederstand = luftwiederstand;
	}

	public boolean isInteracted() {
		return Interacts;
	}

	private void setInteracted(boolean interacts) {
		Interacts = interacts;
	}

}
